#include "VAmpLib.h"

VAmpLib::VAmpLib()
{
#ifdef HAVE_VAMP_LIBRARY
	isOpen = false;
	Run = false;
	Buffer8 = NULL;
	Buffer16 = NULL;
	Settings = NULL;
#endif
}

VAmpLib::~VAmpLib()
{
#ifdef HAVE_VAMP_LIBRARY
	if (Buffer8 != NULL)
		delete [] Buffer8;
	if (Buffer16 != NULL)
		delete [] Buffer16;
	if (Settings != NULL)
		delete Settings;
#endif
}

#ifdef HAVE_VAMP_LIBRARY
//Check if a device is connected. Him retries 5 time to connect to a device.
int VAmpLib::CheckDevice(void)
{
	int DevCnt = FA_ID_INVALID;
	int nRetries = 0;
	while (nRetries++ <5)
	{
		DevCnt = faGetCount();
		if (DevCnt<1)
			Sleep(500);
		else
			break;
	}
	if (DevCnt == FA_ID_INVALID)
	{
		wxMessageBox(wxT("Please connect the VAmp."),wxT("Error"));
		return -1;
	}
	DeviceId = faGetId(DevCnt-1);
	return 0;
}

int VAmpLib::GetInfo(void)
{
		
	if (DeviceId == FA_ID_INVALID)
	{
		wxMessageBox(wxT("Connection Error."),wxT("Error"));
		return -1;
	}
	if (faOpen(DeviceId)!=FA_ERR_OK)
		return -1;
	
	isOpen = true;
	//Get Info and save number of channels depending on it
	faGetInformation(DeviceId, &DeviceInfo);
	switch (DeviceInfo.Model)
	{
	case FA_MODEL_8:
		ChannelMode = DEVICE_CHANMODE_8;
		Channels = FA_MODEL_8_CHANNELS_MAIN;
		EEGChannels = FA_MODEL_8_CHANNELS_MAIN-1;
		AUXChannels = FA_MODEL_8_CHANNELS_AUX;
		break;
	case FA_MODEL_16:
		ChannelMode = DEVICE_CHANMODE_16;
		Channels = FA_MODEL_16_CHANNELS_MAIN;
		EEGChannels = FA_MODEL_16_CHANNELS_MAIN - 1;
		AUXChannels = FA_MODEL_16_CHANNELS_AUX;
		break;
	default:
		break;
	}

	//Get device proprerties and set the acquisition mode
	faGetProperty(DeviceId, &DeviceProp);
	return 0;

}

//Connect the device depending on DeviceId got with CheckDevice
int VAmpLib::VAmpConnect(t_faDataMode mode)
{
	int refCh;
	DataMode = mode;

	if (DataMode!= dmNormal)
	{
		ChannelMode = DEVICE_CHANMODE_4;
		EEGChannels = FA_MODE_20_KHZ_CHANNELS_MAIN;
		AUXChannels = 0;
		Settings = new t_faDataModeSettings();
		memset(Settings, 0, sizeof(Settings));
		
		//Set Bipolar Channel - Ch - Ref
		if (DeviceInfo.Model == FA_MODEL_8)
			refCh = FA_MODEL_8_CHANNELS_MAIN-1;
		else
			refCh = FA_MODEL_16_CHANNELS_MAIN-1;

		for (int i=0; i < FA_MODE_20_KHZ_CHANNELS_MAIN; i++)
		{
			Settings->Mode20kHz4Channels.ChannelsPos[i] = i;
			Settings->Mode20kHz4Channels.ChannelsNeg[i] = -1;
		}
		faSetDataMode(DeviceId,mode,Settings);
	}
	else
		faSetDataMode(DeviceId,mode,NULL);
	return 0;
}

//Start acquisition
int VAmpLib::VAmpStart(void)
{
	if (!isOpen)
		return -1;
	if (Run)
		return 0;
	if (DeviceId == FA_ID_INVALID)
		return -1;
	
	switch (StartMode)
	{
	case IAC_AT_IMPEDANCE:
		if (DataMode != dmNormal) 
		{
			if (Run)
				faStop(DeviceId);
		}
		faSetDataMode(DeviceId,dmNormal,NULL);
		if (faStart(DeviceId)!=FA_ERR_OK)
			return -1;
		if (faStartImpedance(DeviceId)!=FA_ERR_OK)
			return -1;
		break;
	case IAC_AT_CALIBRATION:
		if (faStart(DeviceId)!=FA_ERR_OK)
			return -1;
		if (faStartCalibration(DeviceId)!=FA_ERR_OK)
			return -1;
		break;
	default:
		if (faStart(DeviceId)!=FA_ERR_OK)
			return -1;
		break;
	}
	Run = true;
	return 0;
}

//Stop and close the communication with the device
int VAmpLib::VAmpStop (void)
{
	if (Run)
	{
		if (DeviceId != FA_ID_INVALID)
		{
			switch (StartMode)
			{
			case IAC_AT_IMPEDANCE:
				faStopImpedance(DeviceId); // Stop impdedance.
				//delete [] Impedance;
				break;
			case IAC_AT_CALIBRATION: // Calibration
				faStopCalibration(DeviceId); // Stop calibration.
				break;
			}
			faStop(DeviceId); // Stop serving data.
			
			Run = false;
			
			ResetVar();
			return 0;
		}
		else
			return 1;
	}
	return 0;
}

//Close the connection to the device
int VAmpLib::VAmpClose()
{
	if (isOpen) 
	{
		faClose(DeviceId); 
		isOpen = false;
	}
	return 0;
}

//Set the memory usage depending on the SatrtMode (Impedance or Data)
void VAmpLib::SetData(int mode, bool FastMode)
{
	int PointsPerBlock =0;
	
	StartMode = mode;
	switch (StartMode)
	{
	case IAC_AT_DATA:
		if (DeviceProp.RateEeg*0.001*DEVICE_GET_DATA_INTERVAL>1)
			PointsPerBlock = DeviceProp.RateEeg*0.001*DEVICE_GET_DATA_INTERVAL;
		if (FastMode == false)
		{
			switch (DeviceInfo.Model)
			{
			case FA_MODEL_8:
				//Buffer8.resize(PointsPerBlock*sizeof(t_faDataModel8));
				Buffer8 = new t_faDataModel8[PointsPerBlock];
				MaxBufSize = int(sizeof(t_faDataModel16)*PointsPerBlock);
				pBuffer = (char*)&Buffer8[0];
				break;
			case FA_MODEL_16:
				Buffer16 = new t_faDataModel16[PointsPerBlock];
				//Buffer16.resize(PointsPerBlock*sizeof(t_faDataModel16));
				MaxBufSize = int(sizeof(t_faDataModel16)*PointsPerBlock);
				pBuffer = (char*)&Buffer16[0];
				break;
			}
		}
		else
		{
			Buffer20k = new t_faDataFormatMode20kHz[PointsPerBlock];
			MaxBufSize = int(sizeof(t_faDataFormatMode20kHz)*PointsPerBlock);
			pBuffer = (char*)&Buffer20k[0];
		}
		break;
	case IAC_AT_IMPEDANCE:
		Impedance = new unsigned int[Channels+1];
		break;
	}

}
//Get data depending on StartMode and DataMode
void* VAmpLib::GetData(void)
{
	int ret;
	int LenToRead;
	int writePos;
	switch (StartMode)
	{
	case IAC_AT_DATA:
		LenToRead = MaxBufSize;
		writePos = 0;
		do
		{
			ret = faGetData(DeviceId,&pBuffer[writePos],LenToRead);
			if (ret<0)
				break;
			else if (ret==0)
				Sleep(DEVICE_GET_DATA_INTERVAL);
			else
			{
				LenToRead -= ret;
				writePos += ret;
			}
		}while(LenToRead>0);
		return pBuffer;		
		break;
	case IAC_AT_IMPEDANCE:
		faGetImpedance(DeviceId,Impedance,sizeof(unsigned int)*Channels);
		return Impedance;
		break;
	}
	return NULL;
}

void VAmpLib::ResetVar(void)
{
	memset(&DeviceInfo, 0, sizeof(DeviceInfo));
	memset(&DeviceProp, 0, sizeof(DeviceProp));
	memset(&Settings, 0, sizeof(Settings));
	
	Channels = 0;
	//Initializing device
	DeviceId = FA_ID_INVALID;	//Device identifier
	StartMode = IAC_AT_DATA;	//Standard Acquisition Mode
	EEGChannels = 0;			//Max numbers of EEG->
	AUXChannels = 0;			//Max numbers of AUX

	isOpen = false;
	Run = false;
}
#endif